package translator

import (
	"fmt"
	"gorm.io/gorm"
	"reflect"
)

// BatchTranslatorFunc 批量翻译函数
type BatchTranslatorFunc func(db *gorm.DB, ids []any) (map[any]string, error)

// BatchTranslateStructs 对切片结构体批量翻译指定字段
func BatchTranslateStructs(db *gorm.DB, list any, translators map[string]BatchTranslatorFunc) error {
	v := reflect.ValueOf(list)
	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Slice {
		return fmt.Errorf("list 必须是切片的指针")
	}
	v = v.Elem() // 获取切片值

	if v.Len() == 0 {
		return nil
	}

	// 提取所有需要翻译的 ID
	translateMap := make(map[string]map[any]struct{}) // 存储待翻译的字段及其 ID
	for i := 0; i < v.Len(); i++ {
		item := v.Index(i).Elem() // 获取 struct
		t := item.Type()

		for j := 0; j < t.NumField(); j++ {
			field := t.Field(j)
			translateTag := field.Tag.Get("translate")
			if translateTag == "" {
				continue
			}

			// 提取 ID 值
			fieldValue := item.Field(j)
			if fieldValue.IsValid() && fieldValue.CanInterface() {
				id := fieldValue.Interface()
				if id != nil {
					if _, exists := translateMap[translateTag]; !exists {
						translateMap[translateTag] = make(map[any]struct{})
					}
					translateMap[translateTag][id] = struct{}{}
				}
			}
		}
	}

	// 进行批量查询
	results := make(map[string]map[any]string) // 存储翻译结果
	for key, ids := range translateMap {
		if translator, ok := translators[key]; ok {
			idList := make([]any, 0, len(ids))
			for id := range ids {
				idList = append(idList, id)
			}

			// 执行批量查询
			translatedMap, err := translator(db, idList)
			if err != nil {
				return fmt.Errorf("翻译 %s 失败: %v", key, err)
			}
			results[key] = translatedMap
		}
	}

	// 赋值翻译结果
	for i := 0; i < v.Len(); i++ {
		item := v.Index(i).Elem()
		t := item.Type()

		for j := 0; j < t.NumField(); j++ {
			field := t.Field(j)
			translateTag := field.Tag.Get("translate")
			if translateTag == "" {
				continue
			}

			// 获取翻译结果
			fieldValue := item.Field(j)
			id := fieldValue.Interface()
			if nameMap, exists := results[translateTag]; exists {
				if name, found := nameMap[id]; found {
					nameField := item.FieldByName(field.Name + "Name")
					if nameField.IsValid() && nameField.CanSet() && nameField.Kind() == reflect.String {
						nameField.SetString(name)
					}
				}
			}
		}
	}

	return nil
}
